package com.example.shop.service.impl;

import com.example.shop.converter.OrderFormToOrder;
import com.example.shop.converter.OrderFormToOrderItem;
import com.example.shop.domain.Order;
import com.example.shop.domain.OrderItem;
import com.example.shop.domain.Product;
import com.example.shop.dto.CartDTO;
import com.example.shop.enums.*;
import com.example.shop.exception.ShopException;
import com.example.shop.form.OrderForm;
import com.example.shop.repository.OrderRepository;
import com.example.shop.service.OrderService;
import com.example.shop.service.ProductService;
import com.example.shop.utils.ExportExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private ExportExcelUtil exportExcelUtil;

    /**
     * 时间限定，若创建的订单的时间超过该限定，则将状态修改为作废订单
     */
    private static final long LIMIT_TIME = 15 * 60 * 1000;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ProductService productService;



    @Override
    @Transactional
    public Order create(OrderForm orderForm, String openid) {

        Long orderAmount = 0L;
        Order order = OrderFormToOrder.convert(orderForm);
        order.setOrderStatus(0);
        List<CartDTO> cartDTOList = OrderFormToOrderItem.convert(orderForm);
        List<OrderItem> orderItemList = new ArrayList<>();

        //查询商品（数量  价格）
        for (CartDTO item : cartDTOList) {
            Product product = productService.findOne(item.getProductId());
            if (product == null) {
                throw new ShopException("创建订单错误：  商品不存在");
            }

            //初步 计算商品总价
//            orderAmount = orderAmount+(product.getPrice()*item.getCount());
            //TODO:  cesi   gaidong
            orderAmount = 1l;

            //将购物车中每件商品添加到OrderItem中
            OrderItem orderItem = new OrderItem();
            orderItem.setProduct(product);
            orderItem.setCount(item.getCount());
            orderItemList.add(orderItem);
        }
        //TODO:总价 ---- 打折后的 金额计算

        //将订单 写入 数据库
        for (OrderItem item : orderItemList) {
            order.getItems().add(item);
        }
        order.setAmount(orderAmount);
        order.setOrderStatus(OrderStatusEnum.NOT_PAY_STATUS.getCode());
        order.setPayStatus(PayStatusEnum.WAIT.getCode());
        order.setOpenid(openid);
        orderRepository.save(order);
        //扣库存
        productService.decreaseStock(cartDTOList);

        return order;
    }

    /**
     * 根据订单id取消订单，取消成功，则会增加库存
     * @param orderId 订单的id
     * @return 成功的订单信息, 若取消失败则抛出异常
     */
    @Override
    @Transactional
    public Order cancel(String orderId) {
        //判断订单状态 （如果订单已完结则不能取消）
        Order order = orderRepository.findOne(orderId);
        if (!order.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) {
            log.error("取消订单 订单状态不正确  Id={},orderStatus={}", order.getId(), order.getOrderStatus());
            throw new ShopException(ResultExceptionEnum.ORDER_STATUS_ERROR);
        }
        //返回库存
        if (order.getItems().isEmpty()) {
            log.error("取消订单 订单中无商品,order={}", order);
            throw new ShopException(ResultExceptionEnum.ORDER_DETAIL_EMPTY);
        }
        List<CartDTO> cartDTOList = order.getItems().stream()
                .map(e -> new CartDTO(e.getProduct().getId(), e.getCount()))
                .collect(Collectors.toList());
        productService.increaseStock(cartDTOList);


        order.setOrderStatus(OrderStatusEnum.CANCEL.getCode());

        return order;

    }

    @Override
    public void delete(String orderId) {
        orderRepository.delete(orderId);
    }

    @Override
    @Transactional
    public Order paid(String orderId) {
        Order order = orderRepository.findOne(orderId);


        //判断支付状态
        if (!order.getOrderStatus().equals(OrderStatusEnum.NOT_PAY_STATUS.getCode())) {
            log.error("订单支付 订单支付状态不正确, order{}", order);
            throw new ShopException(ResultExceptionEnum.ORDER_PAY_STATUS_ERROR);
        }

        order.setOrderStatus(OrderStatusEnum.NEW.getCode());
        Order result = orderRepository.save(order);
        if (result == null) {
            log.error("订单支付 更新失败 order={}", order);
            throw new ShopException(ResultExceptionEnum.ORDER_UPDATE_FAIL);
        }
        //支付成功，判断并设置订单状态
        predicateOrderType(order);
        return order;
    }

    /**
     * 根据指定的订单判断订单的类型，并设置
     * @param order 指定的订单
     */
    private void predicateOrderType(Order order) {
        boolean isService = order.getItems().stream().
                anyMatch(item -> item.getProduct().getType().equals(ProductTypeEnum.SERVICE.getCode()));
        boolean isPracticality = order.getItems().stream().
                anyMatch(item -> item.getProduct().getType().equals(ProductTypeEnum.PRACTICALITY.getCode()));
        if (isService && isPracticality) {
            order.setOrderType(OrderTypeEnum.SYNTHESIZE_TYPE.getCode());
        }
        if (isService) {
            order.setOrderType(OrderTypeEnum.SERVICE_TYPE.getCode());
        }
        if (isPracticality) {
            order.setOrderType(OrderTypeEnum.PRACTICALITY_TYPE.getCode());
        }
    }

    /**
     * 根据订单id,将已导出订单状态改为完结订单
     *
     * @param orderId 订单的id
     * @return 返回完结订单
     */
    @Override
    @Transactional
    public Order finish(String orderId) {
        //判断订单状态
        Order order = orderRepository.findOne(orderId);
        if (!order.getOrderStatus().equals(OrderStatusEnum.EXPORT.getCode())) {
            log.error("完结订单  订单状态不正确， orderId={},orderStatus={}", order.getId(), order.getOrderStatus());
            throw new ShopException(ResultExceptionEnum.ORDER_STATUS_ERROR);
        }

        //修改订单状态
        order.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        Order result = orderRepository.save(order);
        if (result == null) {
            log.error("完结订单 更新失败 order={}", order);
            throw new ShopException(ResultExceptionEnum.ORDER_UPDATE_FAIL);
        }
        return order;
    }

    @Override
    public Page<Order> findAll(Pageable pageable) {
        return orderRepository.findAll(pageable);
    }

    @Override
    public List<Order> findAll() {
        return orderRepository.findAll();
    }

    @Override

    public Order findOne(String orderId) {
        Order order = orderRepository.findOne(orderId);

        if (order == null) {
            log.error("根据id查找订单  订单不存在 order={}", order);
            throw new ShopException(ResultExceptionEnum.ORDER_NOT_EXIST);
        }
        return order;
    }


    @Override
    public Page<Order> findByOpenid(String openid, Pageable pageable) {
        return orderRepository.findByOpenid(openid, pageable);
    }

    @Override
    public Page<Order> findByOrderStatus(Integer orderStatus, Pageable pageable) {
        return orderRepository.findByOrderStatus(orderStatus, pageable);
    }

    @Override
    public List<Order> findByOrderStatus(Integer orderStatus) {
        return orderRepository.findByOrderStatus(orderStatus);
    }

    @Override
    public List<Order> findByProductType(Integer ProductType) {
        List<Order> result = new ArrayList<>();
        List<Order> orders = orderRepository.findAll();
        for (Order order : orders) {
            for (OrderItem orderItem : order.getItems()) {
                if (orderItem.getProduct().getType().equals(ProductType)) {
                    result.add(order);
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public List<Order> findByProductSeller(String seller) {
        List<Order> result = new ArrayList<>();
        List<Order> orders = orderRepository.findAll();
        for (Order order : orders) {
            for (OrderItem orderItem : order.getItems()) {
                if (orderItem.getProduct().getSeller().equals(seller)) {
                    result.add(order);
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public List<Order> save(List<Order> orderList) {
        return orderRepository.save(orderList);
    }

    /**
     * 每隔5秒钟执行一次该方法，所有未创建的订单超过15分钟未付款，则将订单的状态修改为作废订单
     */
    @Override
    @Scheduled(fixedRate = 60_000)
    public void invalidOrders() {
        long currentTime = System.currentTimeMillis();
        List<Order> createOrders = orderRepository.findByOrderStatus(OrderStatusEnum.NOT_PAY_STATUS.getCode());
        List<Order> collect = createOrders.stream().filter(order -> currentTime - order.getCreatetime() > LIMIT_TIME).collect
                (Collectors.toList());
        collect.forEach(order -> order.setOrderStatus(OrderStatusEnum.CANCEL.getCode()));
        orderRepository.save(collect);
    }

    @Override
    public void exportByOrderStatusAndOrderType(HttpServletResponse response, Integer orderStatus, Integer orderType) {
        List<Order> orderList = orderRepository.findByOrderStatusAndOrderType(orderStatus, orderType);
        List<Order> addOrders = orderRepository.findByOrderStatusAndOrderType(orderStatus,
                OrderTypeEnum.SYNTHESIZE_TYPE.getCode());
        orderList.addAll(addOrders);

        exportExcelUtil.returnOrder(orderList, response);
        if (orderStatus.equals(OrderStatusEnum.NEW.getCode())) {
            orderList.forEach(order -> order.setOrderStatus(OrderStatusEnum.EXPORT.getCode()));
            save(orderList);
        }
    }

    @Override
    public Order findByOrderNumber(String orderNumber) {
        Order order = orderRepository.findByNumber(orderNumber);
        if (order == null) {
            log.error("根据number查找订单  订单不存在 order={}", order);
        }
        return order;
    }

    @Override
    public Map<Integer, Long> statisticsOrder(long startTime, long endTime) {
        List<Order> orderList = orderRepository.findByCreatetimeBetween(startTime, endTime);
        Map<Integer, Long> map = orderList.stream().collect(Collectors.groupingBy(Order::getOrderStatus, Collectors
                .counting()));
        long unfinishedOrder = map.get(OrderStatusEnum.NEW.getCode()) + map.get(OrderStatusEnum.EXPORT.getCode());
        map.put(OrderStatusEnum.UN_FINISHED.getCode(), unfinishedOrder);
        map.put(OrderStatusEnum.ALL_ORDER.getCode(), (long) orderList.size());
        return map;
    }

    @Override
    public Page<Order> findByOrderType(PageRequest pageRequest, Integer orderType) {
        return orderRepository.findByOrderTypeOrOrderType(orderType, OrderTypeEnum.SYNTHESIZE_TYPE.getCode(), pageRequest);
    }

    @Override
    public Page<Order> findByOrderTypeAndOrderStatus(Integer orderType, Integer orderStatus, PageRequest pageRequest) {
        return orderRepository.findByOrderTypeOrOrderTypeAndOrderStatus(
                orderType,OrderTypeEnum.SYNTHESIZE_TYPE.getCode(),orderStatus,pageRequest);
    }

    @Override
    public List<Order> finByOrderTime(String startTime, String endTime) {
        return orderRepository.findByCreatetimeBetween(Long.valueOf(startTime), Long.valueOf(endTime));
    }


}
